package com.sgcc.ln.pmos.common.interceptor;

import android.text.TextUtils;
import android.util.Log;

import com.alibaba.android.arouter.launcher.ARouter;
import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.impl.ConfirmPopupView;
import com.lxj.xpopup.interfaces.OnCancelListener;
import com.lxj.xpopup.interfaces.OnConfirmListener;
import com.sgcc.ln.pmos.arouter.app.AppArouterPath;
import com.sgcc.ln.pmos.common.bean.EventCenter;
import com.sgcc.ln.pmos.common.dialog.CommonDialog;
import com.sgcc.ln.pmos.common.http.HttpInterConst;
import com.sgcc.ln.pmos.common.interceptor.formatter.JSONFormatter;
import com.sgcc.ln.pmos.common.utils.ArguConstant;
import com.sgcc.ln.pmos.common.utils.ConfigUtil;
import com.sgcc.ln.pmos.common.utils.UserManager;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import okhttp3.Connection;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okhttp3.internal.platform.Platform;
import okio.Buffer;
import okio.BufferedSource;

public class SignInterceptor implements Interceptor {
    //    ;JSESSIONID=3D7394CDC92EE64C7C2FBEA8648B1634
    public static String Authorization = "X-Ticket=%s; Admin-Token20090=%s";
    public static String marketId = "";
    private static final Charset UTF8 = Charset.forName("UTF-8");
    private static final AtomicInteger ID_GENERATOR = new AtomicInteger(0);
    private final Logger logger;
    private boolean is401 = false;

    public SignInterceptor() {
        this(new Logger() {
            @Override
            public void log(String message) {
                if (AppUtils.isAppDebug()) {
                    Platform.get().log(Platform.WARN, message, null);
                }
            }
        });
    }

    public SignInterceptor(Logger logger) {
        this.logger = logger;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request.Builder builder = chain.request().newBuilder();
        Set<String> names = request.headers().names();
        if (!names.contains("Cookie")) {
            builder.addHeader("Cookie", Authorization);
        }
//        if (HttpInterConst.isRelease) {
        builder.addHeader("ClientTag", "MOVE_APP");
//        } else {
//            builder.addHeader("ClientTag", "OUTNET_BROWSE");
//        }
        final int id = ID_GENERATOR.incrementAndGet();

        final String LOG_PREFIX = "[" + id + " request]";
        RequestBody requestBody = request.body();
        boolean hasRequestBody = requestBody != null;

        Connection connection = chain.connection();
        Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
        String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
        boolean isNotJsonBody = false;
        if (hasRequestBody) {
            if (!"application/json; charset=utf-8".equals(requestBody.contentType().toString())) {
                if (requestBody.contentType() != null) {
                    logger.log(LOG_PREFIX + "Content-Type: " + requestBody.contentType());
                }
                if (requestBody.contentLength() != -1) {
                    logger.log(LOG_PREFIX + "Content-Length: " + requestBody.contentLength());
                }
                isNotJsonBody = true;
            }
        }
        boolean notIncludeRequestCount = true;
        String bodyString_sign = "";
        if (!hasRequestBody) {
            logger.log(LOG_PREFIX + requestStartMessage);
            logger.log(LOG_PREFIX + "--> END " + request.method());
        } else if (bodyEncoded(request.headers())) {
            logger.log(LOG_PREFIX + requestStartMessage);
            logger.log(LOG_PREFIX + "--> END " + request.method() + " (encoded body omitted)");
        } else {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);

            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }

            if (isPlaintext(buffer)) {
                if (!isNotJsonBody) {
                    final String bufferString = buffer.readString(charset);
                    notIncludeRequestCount = !bufferString.contains("requestCount");
                    if (notIncludeRequestCount) {
                        logger.log(LOG_PREFIX + requestStartMessage);
                        logger.log(LOG_PREFIX + "body加密前" + bufferString);
                    }
                } else {
                    logger.log(LOG_PREFIX + requestStartMessage);
                }
            } else {
                logger.log(LOG_PREFIX + requestStartMessage);
                logger.log(LOG_PREFIX + "--> END " + request.method() + " (binary "
                        + requestBody.contentLength() + "-byte body omitted)");
            }
        }
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("data", bodyString_sign);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        if (notIncludeRequestCount && ConfigUtil.IS_OPEN_JIAMI)
            logger.log(LOG_PREFIX + "body加密后" + jsonObject.toString());
        if (ConfigUtil.IS_OPEN_JIAMI) {
            if (!isNotJsonBody) {
                request = builder.post(RequestBody.create(requestBody.contentType(), jsonObject.toString())).build();
            } else {
                request = builder.post(requestBody).build();
            }
        } else {

            String method = request.method();
            if ("GET".equals(method)) {
                request = builder.get().build();
            } else {
                request = builder.post(requestBody).build();
            }

        }
        Headers headers = request.headers();
        HashMap<String, String> mHeaders = new HashMap<>();
        for (int i = 0, count = headers.size(); i < count; i++) {
            String name = headers.name(i);
            String value = headers.value(i);
            if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name) && !TextUtils.isEmpty(value)) {
                if (notIncludeRequestCount) {
                    mHeaders.put(name, value);
                    logger.log(LOG_PREFIX + name + ": " + value);
                }
            }
        }
        if (notIncludeRequestCount) {
            logger.log(LOG_PREFIX + "totalHeader全部请求头----" + ": " + mHeaders.toString());

            String method = request.method();
            if ("GET".equals(method)) {
                logger.log(LOG_PREFIX + "--> END " + request.method());
            } else {
                logger.log(LOG_PREFIX + "--> END " + request.method() + " (" + requestBody.contentLength() + "-byte body)");
            }

        }
        final String LOG_PREFIX2 = "[" + id + " response]";
        long startNs = System.nanoTime();
        Response response;
        try {
            response = chain.proceed(request);
        } catch (Exception e) {
            if (notIncludeRequestCount) logger.log(LOG_PREFIX2 + "<-- HTTP FAILED: " + e);
            throw e;
        }
        long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);

        ResponseBody responseBody = response.body();
        long contentLength = responseBody.contentLength();
        if (notIncludeRequestCount)
            logger.log(LOG_PREFIX2 + "<-- " + response.code() + ' ' + response.message() + ' ' + response.request().url() + " (" + tookMs + "ms" + "" + ')');
        if (!HttpHeaders.hasBody(response)) {
            if (notIncludeRequestCount) logger.log(LOG_PREFIX2 + "<-- END HTTP");
        } else if (bodyEncoded(response.headers())) {
            if (notIncludeRequestCount)
                logger.log(LOG_PREFIX2 + "<-- END HTTP (encoded body omitted)");
        } else {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
            Charset charset = UTF8;
            MediaType contentType = responseBody.contentType();
            if (contentType != null) {
                try {
                    charset = contentType.charset(UTF8);
                } catch (UnsupportedCharsetException e) {
                    if (notIncludeRequestCount) {
                        logger.log(LOG_PREFIX2 + "");
                        logger.log(LOG_PREFIX2 + "Couldn't decode the response body; charset is likely malformed.");
                        logger.log(LOG_PREFIX2 + "<-- END HTTP");
                    }
                    return response;
                }
            }

            if (!isPlaintext(buffer)) {
                if (notIncludeRequestCount)
                    logger.log(LOG_PREFIX2 + "<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
                return response;
            }

            if (contentLength != 0) {
                String bufferString = buffer.clone().readString(charset);
                try {
                    if (notIncludeRequestCount) {
                        logger.log(LOG_PREFIX2 + "返回值未加密----" + bufferString);
                        if (contentType != null && "json".equals(contentType.subtype())) {
                            logger.log(LOG_PREFIX2 + "\n" + JSONFormatter.formatJSON(bufferString));
                        }
                        logger.log(LOG_PREFIX2 + "<-- END HTTP (" + buffer.size() + "-byte body)");
                    }


                    JSONObject jsonObject1 = new JSONObject(bufferString);
                    String url = response.request().url().toString();
                    String status = null, code = null, msg = null;
                    if (bufferString.contains("status")) {
                        status = jsonObject1.getString("status");
                    } else {
                        code = jsonObject1.getString("code");
                        msg = jsonObject1.getString("msg");
                    }
                    if ("401".equals(status)) {
                        if (!is401) {
                            is401 = true;
                            UserManager.logout();
                            ThreadUtils.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    showLogoutDialog();
                                }
                            });
                        }
                    }

                    if (!TextUtils.isEmpty(code) && !TextUtils.isEmpty(msg) && UserManager.isLogin()) {
                        if ("500".equals(code) && "用户未登录".equals(msg)) {
                            UserManager.logout();
                            ThreadUtils.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    showLogoutDialog();
                                }
                            });
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (notIncludeRequestCount)
                logger.log(LOG_PREFIX2 + "<-- END HTTP (" + buffer.size() + "-byte body)");
        }


        return response;
    }

    static boolean isPlaintext(Buffer buffer) {
        try {
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64 ? buffer.size() : 64;
            buffer.copyTo(prefix, 0, byteCount);
            for (int i = 0; i < 16; i++) {
                if (prefix.exhausted()) {
                    break;
                }
                int codePoint = prefix.readUtf8CodePoint();
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false;
                }
            }
            return true;
        } catch (EOFException e) {
            return false; // Truncated UTF-8 sequence.
        }
    }

    private boolean bodyEncoded(Headers headers) {
        String contentEncoding = headers.get("Content-Encoding");
        return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
    }

    public interface Logger {
        void log(String message);
    }

    public void showLogoutDialog() {
//        if (confirmPopupView == null) {
        new XPopup.Builder(ActivityUtils.getTopActivity())
                .dismissOnBackPressed(false)
                .dismissOnTouchOutside(false)
                .asConfirm("温馨提示", "您的登录信息已失效,是否重新登录？",
                        "取消", "重新登录",
                        new OnConfirmListener() {
                            @Override
                            public void onConfirm() {
                                is401 = false;
                                ARouter.getInstance()
                                        .build(AppArouterPath.APP_LOGIN)
                                        .navigation();

                            }
                        }, new OnCancelListener() {
                            @Override
                            public void onCancel() {
                                is401 = false;
                                ARouter.getInstance()
                                        .build(AppArouterPath.APP_MAIN)
                                        .navigation();
                            }
                        }, false).show();
//        }
    }
}